package org.linlinjava.litemall.core.util;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.linlinjava.litemall.db.domain.TGoods;
import org.linlinjava.litemall.db.enumeration.Const;
import org.springframework.beans.BeanUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * 通用工具类
 */
public class Util {

    private static ExecutorService simpleThread = Executors.newSingleThreadExecutor();

    public static void runTask(Runnable task) {
        simpleThread.execute(task);
    }

    public static void runTaskLately(Runnable task) {
        simpleThread.execute(task);
    }

    public static ThreadLocal<Boolean> hadShow = new ThreadLocal<>();

    public static void copy(Object source, Object target) {
        BeanUtils.copyProperties(source, target);
    }

    public static <K, V> Map<K, V> hMap() {
        Map<K, V> map = Maps.newHashMap();
        return map;
    }

    public static <K, V> Map<K, V> lhMap() {
        Map<K, V> map = Maps.newLinkedHashMap();
        return map;
    }

    public static <E> List<E> pageList(List page) {
        return new PageList(page);
    }


    public static <E> List<E> aList(E... type) {
        List<E> res = Lists.newArrayList();
        if (type.length == 0)
            return res;
        for (E e : type) {
            res.add(e);
        }
        return res;
    }

    public static <E> List<E> aList() {
        return Lists.newArrayList();
    }

    public static <E> List<E> aLinkedList() {
        return Lists.newLinkedList();
    }

    public static <E> List<E> aList(int arraySize) {
        return Lists.newArrayListWithCapacity(arraySize);
    }

    public static <E> List<E> aList(List<E> arr) {
        return Lists.newArrayList(arr);
    }

    public static <E> Set<E> aSet() {
        return Sets.newHashSet();
    }


    /**
     * 计算两个经纬度之间的距离
     *
     * @return 单位米
     */
    public static Double calcDistance(Double aLongitude, Double aLatitude, Double bLongitude, Double bLatitude) {
        return distance(aLatitude, bLatitude, aLongitude, bLongitude);
    }

    /**
     * 计算两个经纬度之间的距离
     *
     * @return 单位千米
     */
    public static Double calcKmDistance(Double aLongitude, Double aLatitude, Double bLongitude, Double bLatitude) {
        double distance = distance(aLatitude, bLatitude, aLongitude, bLongitude);
        distance = distance / 1000;
        return retain2(distance);
    }

    public static double distance(double lat1, double lat2, double lon1, double lon2) {
        final int R = 6371; // 地球半径
        double latDistance = Math.toRadians(lat2 - lat1);
        double lonDistance = Math.toRadians(lon2 - lon1);
        double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
                + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2))
                * Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        double distance = R * c * 1000; // 单位转换成米
        distance = Math.pow(distance, 2);
        return Math.sqrt(distance);
    }

    public static double distance0(double lat1, double lng1, double lat2, double lng2) {
        double radLat1 = Math.toRadians(lat1);
        double radLat2 = Math.toRadians(lat2);
        double a = radLat1 - radLat2;
        double b = Math.toRadians(lng1) - Math.toRadians(lng2);
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) +
                Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
        s = s * 6378.137d;
        s = new BigDecimal(s).setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue();
        return s;
    }
    /**
     * 保留两位小数
     *
     * @param n
     * @return
     */
    public static double retain2(double n) {
        return (double) Math.round(n * 100) / 100;
    }


    /**
     * 复制一个商品
     *
     * @param source
     * @return
     */
    public static TGoods getNewGoods(TGoods source) {
        TGoods newGoods = new TGoods();
        copy(source, newGoods);
        newGoods.setId(null);
        return newGoods;
    }

    public static Boolean checkDNum(Double n) {
        return n == null || n <= 0;
    }
}
